/**
 * 会话管理服务
 * Session Management Service
 */

const { v4: uuidv4 } = require('uuid');
const jwt = require('jsonwebtoken');
const config = require('../config/config');
const logger = require('../utils/logger');

class SessionService {
  constructor() {
    this.sessions = new Map(); // 内存会话存储
    this.userSessions = new Map(); // 用户ID到会话ID的映射
    
    // 启动定期清理任务
    this.startCleanupTask();
  }

  /**
   * 创建新会话
   */
  createSession(user, options = {}) {
    const sessionId = uuidv4();
    const now = new Date();
    const expiresAt = new Date(now.getTime() + config.security.sessionTimeout);

    const sessionData = {
      sessionId,
      userId: user.id,
      email: user.email,
      nickname: user.nickname,
      role: user.role,
      createdAt: now,
      lastAccess: now,
      expiresAt,
      clientIP: options.clientIP || null,
      userAgent: options.userAgent || null,
      rememberMe: options.rememberMe || false
    };

    // 如果选择了"记住我"，延长会话时间
    if (options.rememberMe) {
      sessionData.expiresAt = new Date(now.getTime() + (30 * 24 * 60 * 60 * 1000)); // 30天
    }

    // 存储会话
    this.sessions.set(sessionId, sessionData);

    // 更新用户会话映射
    if (!this.userSessions.has(user.id)) {
      this.userSessions.set(user.id, new Set());
    }
    this.userSessions.get(user.id).add(sessionId);

    // 生成JWT令牌
    const token = jwt.sign(
      { 
        sessionId,
        userId: user.id,
        role: user.role
      },
      config.jwt.secret,
      { 
        expiresIn: options.rememberMe ? '30d' : config.jwt.expiresIn 
      }
    );

    logger.info('会话创建成功 / Session created successfully', {
      userId: user.id,
      email: user.email,
      sessionId: sessionId.substring(0, 8) + '...',
      rememberMe: options.rememberMe,
      clientIP: options.clientIP
    });

    return {
      token,
      sessionId,
      expiresAt: sessionData.expiresAt
    };
  }

  /**
   * 获取会话信息
   */
  getSession(sessionId) {
    const session = this.sessions.get(sessionId);
    
    if (!session) {
      return null;
    }

    // 检查会话是否过期
    if (new Date() > session.expiresAt) {
      this.destroySession(sessionId);
      return null;
    }

    return session;
  }

  /**
   * 更新会话最后访问时间
   */
  updateLastAccess(sessionId) {
    const session = this.sessions.get(sessionId);
    
    if (session) {
      session.lastAccess = new Date();
      return true;
    }
    
    return false;
  }

  /**
   * 销毁单个会话
   */
  destroySession(sessionId) {
    const session = this.sessions.get(sessionId);
    
    if (!session) {
      return false;
    }

    // 从会话存储中删除
    this.sessions.delete(sessionId);

    // 从用户会话映射中删除
    const userSessionSet = this.userSessions.get(session.userId);
    if (userSessionSet) {
      userSessionSet.delete(sessionId);
      
      // 如果用户没有其他会话，删除映射
      if (userSessionSet.size === 0) {
        this.userSessions.delete(session.userId);
      }
    }

    logger.info('会话销毁成功 / Session destroyed successfully', {
      userId: session.userId,
      sessionId: sessionId.substring(0, 8) + '...'
    });

    return true;
  }

  /**
   * 销毁用户的所有会话
   */
  destroyUserSessions(userId) {
    const userSessionSet = this.userSessions.get(userId);
    
    if (!userSessionSet) {
      return 0;
    }

    let destroyedCount = 0;
    
    for (const sessionId of userSessionSet) {
      if (this.sessions.has(sessionId)) {
        this.sessions.delete(sessionId);
        destroyedCount++;
      }
    }

    // 清除用户会话映射
    this.userSessions.delete(userId);

    logger.info('用户所有会话已销毁 / All user sessions destroyed', {
      userId,
      count: destroyedCount
    });

    return destroyedCount;
  }

  /**
   * 获取用户的活跃会话列表
   */
  getUserSessions(userId) {
    const userSessionSet = this.userSessions.get(userId);
    
    if (!userSessionSet) {
      return [];
    }

    const sessions = [];
    const now = new Date();

    for (const sessionId of userSessionSet) {
      const session = this.sessions.get(sessionId);
      
      if (session && now <= session.expiresAt) {
        sessions.push({
          sessionId: sessionId.substring(0, 8) + '...',
          createdAt: session.createdAt,
          lastAccess: session.lastAccess,
          expiresAt: session.expiresAt,
          clientIP: session.clientIP,
          userAgent: session.userAgent,
          current: false // 需要在调用时设置
        });
      }
    }

    return sessions.sort((a, b) => b.lastAccess - a.lastAccess);
  }

  /**
   * 清理过期会话
   */
  cleanupExpiredSessions() {
    const now = new Date();
    let cleanedCount = 0;

    // 清理过期会话
    for (const [sessionId, session] of this.sessions.entries()) {
      if (now > session.expiresAt) {
        this.destroySession(sessionId);
        cleanedCount++;
      }
    }

    if (cleanedCount > 0) {
      logger.info(`清理过期会话 / Cleaned expired sessions: ${cleanedCount}`);
    }

    return cleanedCount;
  }

  /**
   * 启动定期清理任务
   */
  startCleanupTask() {
    // 每小时清理一次过期会话
    setInterval(() => {
      this.cleanupExpiredSessions();
    }, 60 * 60 * 1000);

    // 启动时立即清理一次
    this.cleanupExpiredSessions();
  }

  /**
   * 获取会话统计信息
   */
  getSessionStats() {
    const now = new Date();
    const activeSessions = [];
    const expiredSessions = [];

    for (const session of this.sessions.values()) {
      if (now <= session.expiresAt) {
        activeSessions.push(session);
      } else {
        expiredSessions.push(session);
      }
    }

    // 统计每个用户的会话数
    const userSessionCounts = {};
    activeSessions.forEach(session => {
      userSessionCounts[session.userId] = (userSessionCounts[session.userId] || 0) + 1;
    });

    return {
      totalSessions: this.sessions.size,
      activeSessions: activeSessions.length,
      expiredSessions: expiredSessions.length,
      uniqueUsers: Object.keys(userSessionCounts).length,
      averageSessionsPerUser: Object.keys(userSessionCounts).length > 0 
        ? (activeSessions.length / Object.keys(userSessionCounts).length).toFixed(2) 
        : 0,
      userSessionCounts
    };
  }

  /**
   * 验证会话并返回用户信息
   */
  validateSession(sessionId) {
    const session = this.getSession(sessionId);
    
    if (!session) {
      return null;
    }

    // 更新最后访问时间
    this.updateLastAccess(sessionId);

    return {
      id: session.userId,
      email: session.email,
      nickname: session.nickname,
      role: session.role,
      sessionId: session.sessionId
    };
  }

  /**
   * 延长会话有效期
   */
  extendSession(sessionId, additionalTime = null) {
    const session = this.sessions.get(sessionId);
    
    if (!session) {
      return false;
    }

    const extensionTime = additionalTime || config.security.sessionTimeout;
    session.expiresAt = new Date(Date.now() + extensionTime);

    logger.debug('会话有效期已延长 / Session extended', {
      sessionId: sessionId.substring(0, 8) + '...',
      newExpiresAt: session.expiresAt
    });

    return true;
  }

  /**
   * 获取会话详细信息（用于管理员）
   */
  getSessionDetails(sessionId) {
    const session = this.sessions.get(sessionId);
    
    if (!session) {
      return null;
    }

    return {
      sessionId: session.sessionId,
      userId: session.userId,
      email: session.email,
      nickname: session.nickname,
      role: session.role,
      createdAt: session.createdAt,
      lastAccess: session.lastAccess,
      expiresAt: session.expiresAt,
      clientIP: session.clientIP,
      userAgent: session.userAgent,
      rememberMe: session.rememberMe,
      isExpired: new Date() > session.expiresAt
    };
  }

  /**
   * 获取所有活跃会话（用于管理员）
   */
  getAllActiveSessions() {
    const now = new Date();
    const activeSessions = [];

    for (const session of this.sessions.values()) {
      if (now <= session.expiresAt) {
        activeSessions.push({
          sessionId: session.sessionId.substring(0, 8) + '...',
          userId: session.userId,
          email: session.email,
          nickname: session.nickname,
          role: session.role,
          createdAt: session.createdAt,
          lastAccess: session.lastAccess,
          expiresAt: session.expiresAt,
          clientIP: session.clientIP,
          rememberMe: session.rememberMe
        });
      }
    }

    return activeSessions.sort((a, b) => b.lastAccess - a.lastAccess);
  }

  /**
   * 强制销毁会话（用于管理员）
   */
  forceDestroySession(sessionId, adminUserId) {
    const session = this.sessions.get(sessionId);
    
    if (!session) {
      return false;
    }

    const destroyed = this.destroySession(sessionId);

    if (destroyed) {
      logger.warn('会话被管理员强制销毁 / Session forcibly destroyed by admin', {
        sessionId: sessionId.substring(0, 8) + '...',
        targetUserId: session.userId,
        adminUserId
      });
    }

    return destroyed;
  }
}

// 创建全局会话服务实例
const sessionService = new SessionService();

module.exports = sessionService;